package com.utils;

import com.graphics.ImageIdentity;
import com.os.OSAttribute;
import com.os.OSBoundingBox;
import com.utils.generated.*;
import com.utils.generated.ObjectFactory;
import java.io.File;
import java.io.FileOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.ListIterator;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import mapgenerator.Main;

/**
 *
 * @author Sajarwo Anggai
 */
public class MapOperation {

    private JAXBContext jc;
    private Project project;
    private ImageManager im;
    private ImagePattern ip;
    private ObjectSprite os;
    private Main comp;

    public MapOperation(Main comp) {
        try {
            this.comp = comp;
            jc = JAXBContext.newInstance(ObjectFactory.class);
        } catch (JAXBException ex) {
        }
    }

    public void openMap(String location) {
        try {
            Unmarshaller u = jc.createUnmarshaller();
            Map map = (Map) u.unmarshal(new File(location));
            List list = (List) map.getLayerManagerOrObjectSpriteOrImagePatternOrImageManagerOrProject();
            ListIterator itr = list.listIterator(0);
            while (itr.hasNext()) {
                Object ob = itr.next();
                if (ob instanceof Project) {
                    project = (Project) ob;
                } else if (ob instanceof ImageManager) {
                    im = (ImageManager) ob;
                } else if (ob instanceof ImagePattern) {
                    ip = (ImagePattern) ob;
                } else if (ob instanceof ObjectSprite) {
                    os = (ObjectSprite) ob;
                }
            }
            loadProject(false, location);
            loadImageManager(false);
            loadPattern(false);
            loadObjectSprite(false);
        } catch (JAXBException ex) {
            System.out.println("Eror occured at Loading XML");
        }
    }

    public void saveMap(String location) {
        try {
            ObjectFactory factory = new ObjectFactory();
            Map map = factory.createMap();
            project = factory.createProject();
            im = factory.createImageManager();
            ip = factory.createImagePattern();
            os = factory.createObjectSprite();

            loadProject(true, "");
            loadImageManager(true);
            loadPattern(true);
            loadObjectSprite(true);
            map.getLayerManagerOrObjectSpriteOrImagePatternOrImageManagerOrProject().add(project);
            map.getLayerManagerOrObjectSpriteOrImagePatternOrImageManagerOrProject().add(im);
            map.getLayerManagerOrObjectSpriteOrImagePatternOrImageManagerOrProject().add(ip);
            map.getLayerManagerOrObjectSpriteOrImagePatternOrImageManagerOrProject().add(os);

            Marshaller marshaller = jc.createMarshaller();
            marshaller.marshal(map, new FileOutputStream(location));

        } catch (Exception ex) {
            System.out.println("Error occured at Saving XML" + ex);
        }
    }

    public void loadProject(boolean save, String location) {
        if (save) {
            project.setName(comp.project.getProjectName());
            project.setProjectDir(comp.project.getProjectName());
            project.setImageDir("images");
            project.setMapWidth("" + comp.project.getMapWidth());
            project.setMapHeigh("" + comp.project.getMapHeight());
            project.setTileWidth("" + comp.project.getTileWidth());
            project.setTileHeight("" + comp.project.getTileHeight());
        } else {
            File f = new File(location);
            comp.project.setProjectName(new File(f.getParent()).getName());
            comp.project.setPath(f.getParent());
            comp.project.setImageDir(f.getParent() + File.separator + project.getImageDir());
            comp.project.setMapWidth(Integer.parseInt(project.getMapWidth()));
            comp.project.setMapHeight(Integer.parseInt(project.getMapHeigh()));
            comp.project.setTileWidth(Integer.parseInt(project.getTileWidth()));
            comp.project.setTileHeight(Integer.parseInt(project.getTileHeight()));
        }
    }

    private void loadImageManager(boolean save) {
        List list;
        if (save) {
            list = comp.imContainer.getImages();
            for (int i = 0; i < list.size(); i++) {
                Image img = new Image();
                img.setName("" + list.get(i));
                im.getImage().add(img);
            }
        } else {
            list = im.getImage();
            for (int i = 0; i < list.size(); i++) {
                comp.imContainer.addImage(((Image) list.get(i)).getName());
            }
        }
    }

    public void loadPattern(boolean save) {
        List list;
        if (save) {
            list = comp.ipContainer.getListImagePattern();
            for (int i = 0; i < list.size(); i++) {
                ImageIdentity imageIdentity = (ImageIdentity) list.get(i);
                Pattern p = new Pattern();
                p.setName(imageIdentity.getName());
                p.setRows("" + imageIdentity.getRows());
                p.setCols("" + imageIdentity.getCols());
                p.setStatus(imageIdentity.isSprite() ? "0" : "1");
                p.setIndex("" + i);
                ip.getPattern().add(p);
            }
        } else {
            list = ip.getPattern();
            for (int i = 0; i < list.size(); i++) {
                Pattern p = (Pattern) list.get(i);
                comp.ipContainer.addImage(p.getName(), Integer.parseInt(p.getRows()), Integer.parseInt(p.getCols()), p.getStatus().equals("0") ? true : false);
            }
        }
    }

    public void loadObjectSprite(boolean save) {
        List list;
        if (save) {
            list = comp.osContainer.getSprites();
            for (int i = 0; i < list.size(); i++) {
                com.os.ObjectSprite obSprite = (com.os.ObjectSprite) list.get(i);
                Sprite s = new Sprite();
                s.setName(obSprite.getName());
                s.setStatus(obSprite.isCharacter() ? "0" : "1");
                if (obSprite.getPosition() != null) {
                    s.setX("" + obSprite.getPosition().x);
                    s.setY("" + obSprite.getPosition().y);
                }
                Iterator itr = obSprite.getAllAttribute().keySet().iterator();
                while (itr.hasNext()) {
                    String key = (String) itr.next();
                    OSAttribute oa = obSprite.getAttribute(key);
                    setItemSprite(s, oa);
                }

                os.getSprite().add(s);
            }
        } else {
            list = os.getSprite();
            for (int i = 0; i < list.size(); i++) {
                Sprite p = (Sprite) list.get(i);
                com.os.ObjectSprite obSprite = new com.os.ObjectSprite(p.getName(), false);
                obSprite.setName(p.getName());

                obSprite.setCharacter(p.getStatus().equals("0"));
                List direc = p.getDirection();
                for (int j = 0; j < direc.size(); j++) {
                    Direction dir = (Direction) direc.get(j);
                    OSAttribute osa = new OSAttribute();
                    osa.setAttributeName(dir.getPosition());
                    osa.setName(dir.getName());
                    osa.setAttrib(comp.ipContainer.getPattern(dir.getName()));
                    osa.setTime(Integer.parseInt(dir.getSpeed()));

                    List bb = dir.getBoundingBox();
                    for (int k = 0; k < bb.size(); k++) {
                        BoundingBox bound = (BoundingBox) bb.get(k);
                        OSBoundingBox osb = new OSBoundingBox();
                        osb.setBounds(Integer.parseInt("" + bound.getX()), Integer.parseInt("" + bound.getY()), Integer.parseInt("" + bound.getWidth()), Integer.parseInt("" + bound.getHeight()));
                        osa.getBound().add(osb);
                    }

                    obSprite.getAllAttribute().put(dir.getPosition(), osa);
                }
                comp.osContainer.addSprites(obSprite);
            }

        }
    }

    public void setItemSprite(Sprite s, OSAttribute osAttribute) {
        Direction direc = new Direction();
        direc.setName(osAttribute.getName());
        ArrayList bounding = osAttribute.getBound();
        for (int bound = 0; bound < bounding.size(); bound++) {
            BoundingBox bb = new BoundingBox();
            OSBoundingBox osb = (OSBoundingBox) bounding.get(bound);
            bb.setX("" + osb.x);
            bb.setY("" + osb.y);
            bb.setWidth("" + osb.width);
            bb.setHeight("" + osb.height);
            direc.getBoundingBox().add(bb);
        }
        direc.setPosition(osAttribute.getAttributeName());
        direc.setSpeed("" + osAttribute.getTime());
        s.getDirection().add(direc);
    }
}
